home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / mush5.7 / part05 < prev    next >
Encoding:
Internet Message Format  |  1987-09-17  |  45.4 KB

  1. Subject:  v11i055:  Mail user's shell, Part05/12
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: island!argv@Sun.COM (Dan Heller)
  7. Posting-number: Volume 11, Issue 55
  8. Archive-name: mush5.7/Part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 12)."
  17. # Contents:  cmd_help fkeys.c select.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'cmd_help' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'cmd_help'\"
  21. else
  22. echo shar: Extracting \"'cmd_help'\" \(16086 characters\)
  23. sed "s/^X//" >'cmd_help' <<'END_OF_FILE'
  24. X/* @(#)cmd_help    1.4    10/28/86 (Dan heller) */
  25. X
  26. X%?%
  27. XThe `?' will give you a list of legal commands.  Most commands
  28. Xaccept -? as an option.  This will give you specialized help
  29. Xwith that particular command.
  30. X%%
  31. X
  32. X%ignore%
  33. Xusage: ignore/unignore [headers]
  34. XUse this command to set the message headers you would like not
  35. Xto be printed when you read a message. If no header specified,
  36. Xthen a list of all headers currently being ignored is printed.
  37. XYou must specify a header for unignore.
  38. X
  39. XYou can set the variable "alwaysignore" to force normally
  40. Xignored headers to be ignored while saving messages, forwarding
  41. Xmessages or including messages into message buffers.
  42. X%%
  43. X
  44. X%set%
  45. Xusage: set/unset [variable] [= value]
  46. Xset by itself prints values for variables in its group
  47. XTo set a boolean variable (on or off), "set variable"
  48. XTo set a variable's value to a string, use:
  49. Xset variable = 'value'
  50. X
  51. XIf you want double-quote's or white-space embedded in
  52. Xa string, encase the string in single quotes.  If you
  53. Xwant single quotes in a string, encase the string in
  54. Xdouble quotes.
  55. X
  56. XType "set ?all" for a list of all settable variables.
  57. X"set ?variable_name" for help on a single variable.
  58. X%%
  59. X
  60. X%readmsg%
  61. XYou can read messages in different ways.  "type" and "print"
  62. Xwill print the current message.  "top" will only print the
  63. Xfirst N lines of the current message where N is the value of
  64. Xthe variable "crt".  "next" will go to the next unread message
  65. Xand print that. "previous" will go back and read the first
  66. Xunread message previous to the current. ^ will print the first
  67. Xmessage, $ will print the last.
  68. XAll can be followed by a message list and each message in
  69. Xthat list will be printed (or piped to other commands).
  70. X%%
  71. X
  72. X%alts_help%
  73. Xusage: alts [hostnames]
  74. Xalts contains a list of hostnames on which you have an account
  75. XNormally, when you respond to all recipients of mail, your
  76. Xaccount name will be listed and you send yourself mail. If you
  77. Xdon't have metoo set, then your name will be removed from the
  78. Xmailing list if your login name is on the list and the host
  79. Xspecified is in the alternates list.  `*' matches all hostnames
  80. Xand only the login name is tested.
  81. X%%
  82. X
  83. X%source_help%
  84. Xusage: source/saveopts [file]
  85. Xsource/saveopts will load/save all variable settings, options,
  86. Xaliases, cmd's, ignored headers ... everything you can set,
  87. Xit loads or saves. The file named used follows these rules:
  88. X
  89. X1) if a filename is given, that file is used.
  90. X2) file described by the environment variable MAILRC
  91. X3) user's home directory: .mailrc
  92. X%%
  93. X
  94. X%general%
  95. XThis is the general help message. To get help on a specific
  96. Xcommand, try "command -?". Extended help is given by typing
  97. X`help item' where item is one of:
  98. X    path, msg_list, prompt, hdr_format.
  99. XHelp with msg_list is highly advisable!
  100. X
  101. XType "?" to get a list of available commands.  Try "? command"
  102. Xto get help on the particular command that you specify.
  103. X%%
  104. X
  105. X%path%
  106. XWhenever "path" is specified, the following syntax is legal besides the
  107. Xnormal path addressing scheme used by unix.
  108. X~[user]     -- the home directory of specified user (yours by default)
  109. X%[user]     --/usr/spool/mail/login_name [user_name] (yours by default)
  110. X+file       --the directory described by `set folder'; file is `file'
  111. X%%
  112. X
  113. X%msg_list%
  114. XA "msg_list" references one or more messages.  The user specifies
  115. Xa group of messages according to a special syntax.
  116. X
  117. X*      All messages.
  118. X^      The first message.
  119. X$      The last message.
  120. X.      The current message.
  121. XN-M    A range of messages between N and M.
  122. X
  123. XIn the last case, N and M may be * ^ $ . or digits referencing
  124. Xexplicit message numbers.  The range must be in ascending order.
  125. X
  126. XYou can also negate messages by placing the message list inside
  127. Xbraces, `{' `}' -- thus, the expression "2-19 {11-14}" references
  128. Xmessages 2 through 19 except for those between 11 through 14.
  129. X
  130. XCommands can be "piped" to one another, because the return
  131. Xvalue of a command is a msg_list, not text.
  132. Xpick -f fred | lpr   will find all messages "from fred" and
  133. Xsend them to the printer.
  134. X
  135. XCommands dealing with more than one message process them in
  136. Xorder -- not necessarily the order specified.  Thus, the command,
  137. Xsave 1-5 9 7 6 file
  138. Xwill save the messages in ascending order; not as specified.
  139. X%%
  140. X
  141. X%preserve_help%
  142. Xusage: preserve [msg_list]
  143. XPreserve saves deleted or read messages in your mailbox.
  144. XWithout explicitely setting preserve, all mail that you
  145. Xread will be saved in ~/mbox (or set mbox).  If you set
  146. X"hold", then this is equivalent to preserving each message
  147. Xas you read it.
  148. X%%
  149. X
  150. X%save_help%
  151. Xusage: save/write/copy [!] [msg_list] [filename]
  152. X
  153. XIf no filename is specified, ~/mbox (or set mbox) is used.
  154. XSave and write will append msg if `file' already exists
  155. XSpecifying the `!' will overwrite file (e.g. erasing it first).
  156. XTo save messages to a filename beginning with a digit,
  157. Xescape the filename with a backslash (\)
  158. X`write' will write message without the headers (msg body only).
  159. XSave and write both mark messages for deletion unless "keepsave"
  160. Xis set.  Copy is identical to save except that messages are not
  161. Xmarked for deletion (identical to having keepsave set).
  162. X%%
  163. X
  164. X%lpr%
  165. Xuse: lpr [-] [-] [msg_list]
  166. X-n         print body of message only (not headers)
  167. X-h         print all headers with message body (default true)
  168. X-       print on printer 
  169. X%%
  170. X
  171. X%respond_help%
  172. Xusage: replysender/replyall [msg_list] [mail_flags] [users]
  173. XReplysender only replies to the sender and replyall responds
  174. Xto everyone on the To: and Cc: lines of the message.
  175. X
  176. XThe commands "repond", "reply", and "r" are identical to
  177. X"replysender." The command, "R" is identical to "replyall."
  178. X
  179. XIf a message list is indicated, then each message on the list is
  180. Xreplied to in the same manner.  All other arguments are passed
  181. Xto the mail command ('mail_flags' and 'users').
  182. X
  183. XType "mail -?" for information on legal mail flags.
  184. X%%
  185. X
  186. X%sort_help%
  187. Xusage: sort [-] [d | a | s | S | R]
  188. X  d         sort according to date received
  189. X  a         author (alphabetical)
  190. X  s         subject ignoring Re: as part of the subject
  191. X  R         subject (alphabetical)
  192. X  S         by status
  193. XThe optional `-' flag will reverse the order of sorting
  194. XBy default (no arguments), sort sorts messages by status:
  195. XNew, unread messages are first, followed by preserved messages
  196. Xand finally the deleted messages are placed at the end
  197. X%%
  198. X
  199. X%pick%
  200. Xuse: pick [-r msg_list] [-d [-][date] ] [-s|f|t]] [-x] [-i] [<pat>]
  201. XSearch for patterns within messages. Entire messages are searched
  202. Xfor <pattern> unless -s, -f, or -t is specified.
  203. XOnly one of -s, -f, -t, and -d can be specified at once. No patterns with -d.
  204. X-r msg_list  restrict the range of messages search to msg_list
  205. X-d: print message headers on or after [`-' before] `date'
  206. X     `date' is of the form: month/date/year
  207. X      Omitted fields default to today's values. Examples:
  208. X      pick -d 4/20     msgs on or after Apr 20, this year
  209. X      pick -d -/2/85   on or before the 2nd, this month, 1985
  210. X      pick -d /        finds today's messages only.
  211. X    At least one `/' char must be used in date.
  212. X    There is no strong date checking; 2/30 would be considered valid
  213. X-s search for pattern in the "subject" headers only.
  214. X-f search for pattern in the "from" field (author) only.
  215. X-t search for pattern in the "to" field.
  216. X-i ignore case of letters.
  217. X-x return those messages which do NOT match.
  218. X%%
  219. X
  220. X%alias%
  221. Xoptions for alias:
  222. Xalias                           print all namelists
  223. Xalias name                      print namelist associated with name
  224. Xalias name namelist             set "name" to value of namelist.
  225. Xunalias namelist                unalias names in namelist
  226. X
  227. XA "namelist" consists of one or more addresses. An address
  228. Xmay be a name already set to another list, valid user, file
  229. Xor program.  Filenames must be full pathnames beginning with
  230. Xa '/' (or a ~ expanding to a home directory).  A "program"
  231. Xmust start with a pipe and be encased in quotes:
  232. X
  233. X    "|program_name"
  234. X
  235. XThe command, "expand", will print addresses (including sublists)
  236. Xassociated with the given alias.
  237. X%%
  238. X
  239. X%from%
  240. XWith no arguments, from will print the current message's header.
  241. XIf given a message list, from will print the headers of those
  242. Xmessages which are in the list.
  243. X
  244. XThe special arguments, `-' and `+' can be given to move the
  245. Xcurrent message pointer to the previous or next message
  246. Xrespectively while also printing that message's header.
  247. X
  248. XIf a message list was given in addition to `-' or `+', then
  249. Xthe current message pointer will be set to the first or last
  250. Xmessage, respectively, in the message list given.
  251. X
  252. Xfrom - 10-30 {16}
  253. Xwill print the headers of messages 10 through 30 except for
  254. Xmessage 16 and set the current message pointer to 10.
  255. X
  256. Xpick -f Dan | from +
  257. Xwill print the headers of all messages that contain Dan in
  258. Xin the author's name and set the current message pointer to
  259. Xthe last one of that kind in the list.
  260. X
  261. Xfrom +
  262. Xwill print the header of the message after the current message
  263. Xand increment the current message pointer to the next message.
  264. X%%
  265. X
  266. X%own_hdrs%
  267. XHere is where you set, unset or view your own message headers.
  268. XThese headers are included in all your outgoing mail.
  269. X
  270. Xoptions for my_hdrs:
  271. Xmy_hdr                          all headers
  272. Xmy_hdr header                   value associated with header
  273. Xmy_hdr header: string           set header to string
  274. Xun_hdr header                   unset header
  275. X%%
  276. X
  277. X%fkey_help%
  278. Xfkey's are function key settings in Suntools (graphics) mode
  279. XWhen run as a tool (-t on command line), choose the Options Item,
  280. Xand the function key menu option.
  281. X%%
  282. X
  283. X%func_help%
  284. Xcmd's are just like aliases in the c-shell.
  285. Xcmd                     view all commands
  286. Xcmd `command'           value associated with command
  287. Xcmd `command' "value"   set command to value
  288. Xuncmd `command'         unset command
  289. X
  290. XIf you want to reference history commands within a cmd,
  291. Xescape the ! with a backslant. For example:
  292. X
  293. Xmail> cmd r 'replysender \!* ; delete -t'
  294. X
  295. Xwill reply using whatever arguments you will have given
  296. Xon the command line and then delete that message and
  297. Xthen print the next message (-t argument to "delete").
  298. X%%
  299. X
  300. X%headers%
  301. Xusage: headers [+ | - | N] [-H:c]
  302. Xprint out a screenful of headers.
  303. X+  print the next screenful.
  304. X-  print the previous screenful.
  305. XN  (where N is a number) print a screenful starting at N.
  306. Xset show_deleted to list deleted messages.
  307. Xcmd h headers        look like UCB-Mail
  308. Xcmd H Headers        show deleted messages (or set show_deleted)
  309. Xcmd z headers +      `z' is next screenful
  310. X
  311. XArguments to the headers command include -H:c where `c' is one of
  312. X    n    just print messages headers of NEW messages
  313. X    d    deleted messages
  314. X    u    unread messages
  315. X    o    old messages
  316. X    a    all messages (mostly for the command line argument -H:c)
  317. X
  318. Xpiping to headers will print the headers of the "output" messages.
  319. X%%
  320. X
  321. X%hdr_format%
  322. Xset hdr_format="string" for changing the display of message headers.
  323. XThe string uses printf style formatting and follows these conventions:
  324. X    %S  message Status.
  325. X    %f  "from" field (author).
  326. X    %a  the address of the author.
  327. X    %n  the name of the author.
  328. X    %t  "to" field (recipients).
  329. X    %d  date of the message.
  330. X    %s  subject of the message.
  331. X    %l  number of lines in the message.
  332. X    %c  number of characters (bytes) in the message.
  333. X    \n  a newline
  334. X    \t  a tab.
  335. XA field specifier may be used.  Thus, %20f will print the first 20
  336. Xcharacters of the from line.  No matter what the formatting string,
  337. Xthe message number followed by a '>' (if current message) is printed.
  338. X%%
  339. X
  340. X%folder_help%
  341. Xusage: folder [-N] [-r] [!] [ %[user] | # | & | file ]
  342. XChange current folder.
  343. XNo arguments prints current folder.
  344. X-N: No headers are displayed upon entering new folder (also command line).
  345. X-r: read only mode (you won't be able to write changes to this folder).
  346. XIf `!' is specified, current folder is not updated.
  347. X%[user] folder to /usr/spool/mail/[user] (you default)
  348. X#  folder accessed previous to current folder
  349. X&  "mbox" -- default is ~/mbox; or set mbox = "file"
  350. X%%
  351. X
  352. X%prompt%
  353. Xset prompt = "string"
  354. X"string" is follows printf style formatting conventions:
  355. X    \t, \n will be replaced by a tab or newline respectively.
  356. X    %m     current message number
  357. X    %t     total number of messages
  358. X    %d     number of deleted messages
  359. X    %u     number of unread messages
  360. X    %n     number of new messages
  361. X    %f     name of the current working folder
  362. X    %T     current time
  363. X    %D     day of the week
  364. X    %Y     year
  365. X    %M     month
  366. X    %N     number of the day in the month (date)
  367. X%%
  368. X
  369. X%quit_help%
  370. Xusage: quit/exit",
  371. Xquit will update your mailbox; if new mail has come in, you will be
  372. Xtold so and given an option whether to really quit or not.
  373. X"exit" will leave mail not updating your mailbox nor check for new mail.
  374. X%%
  375. X
  376. X%ls%
  377. XThe ls command is exactly like the UNIX command, "ls."
  378. XAll arguments are the same.  The variable "lister" can
  379. Xbe set to always default to the same arguments avoiding
  380. Xhaving to specify them all the time.  The "folders"
  381. Xcommand is nothing more than doing "ls $folder" from
  382. Xthe Mush prompt.
  383. X%%
  384. X
  385. X%shell%
  386. Xusage: sh [command]
  387. XIf a "command" is given, that UNIX command will be executed
  388. Xunder the Bourne shell. If no command is specified, then an
  389. Xinteractive shell will be started. The environment variable
  390. XSHELL or the local mail shell variable shell  describes the
  391. Xshell to invoke.  If none is set, then the default shell is
  392. Xdefined by the system administrator (currently set to csh).
  393. X
  394. XUsers on systems with job control will probably have little
  395. Xuse for the sh command.
  396. X%%
  397. X
  398. X%stop%
  399. XThe stop command sends a stop signal to the mail shell.
  400. XIt is equivalent to ^Z as it will stop the process.
  401. XSince the shell never needs to be exited, the command
  402. X'q' may be aliased to "stop" and the shell may have,
  403. X% alias 'mail   ?mush'
  404. Xwhich will bring mush into the foreground rather than
  405. Xhaving to invoke a new shell.  New mail will be read 
  406. Xinto the shell automatically and much time and energy 
  407. Xis saved.
  408. X%%
  409. X
  410. X%curses%
  411. XThe curses-based interface for Mush does not require a graphics
  412. Xdisplay, but does requires a terminal which can handle upline
  413. Xcursor movement capabilities.  All commands are one key-stroke
  414. Xcommands and are executed instantaneously.  A list of curses
  415. Xcommands is given by using the `?' key in curses mode.
  416. X%%
  417. X
  418. X%bind%
  419. XBinding is done for the curses interface only.  It allows
  420. Xthe user to bind keystrokes or key sequences to commands.
  421. X
  422. XTo bind keystrokes that are control characters, you must use
  423. Xthe notation: "\CX" where "X" is in upper-case and it represents
  424. Xthe control key you want to use. "\CN" would be control-N; "\n"
  425. Xis carriage return.  You may not bind keyboard generated signals;
  426. Xfor most users, those key sequences are control-C and control-\.
  427. XFor users with job control, control-Z and control-Y are ignored.
  428. XTo reference the escape key, use the string, "\E".
  429. X
  430. XThe spacebar may not be bound since it is the only way to return
  431. Xto the main level from the "...continue..." prompt.
  432. X
  433. XTrying to bind a key sequence which prefixes another sequence
  434. Xis an error and the user is warned that the longer binding will
  435. Xnot work.
  436. X
  437. XAs always, -? will give help.
  438. X%%
  439. X
  440. X%msg_flags%
  441. Xusage: flags [msg_list [N O R D P U] ]
  442. XThis command displays the state of messages as seen by the internals
  443. Xof Mush.  This is not a documented command, so don't tell anyone.
  444. XIf a list is given (or piped), it will tell which bits of the message
  445. Xare set: New, Old, Read, Deleted, Preserved, or Unread.
  446. XIf any (one or more) of the optional bits are given, then it will set
  447. Xthe appropriate bit in the list given.  As usual, if no list is given,
  448. Xthen the current message is used (or set bits on a pipe).
  449. X%%
  450. X
  451. X%setenv%
  452. Xusage: setenv VARIABLE [value]
  453. X
  454. XVariable names may be any string, but traditionally environment variables
  455. Xare all upper case.  If no "value" is specified, then the variable name
  456. Xwill be set to an empty string.  If the value contains spaces, you should
  457. Xenclose the string in quotation marks.  Use printenv to print a list of
  458. Xall your environment variables.
  459. X%%
  460. X
  461. X%unsetenv%
  462. Xusage: unsetenv VARIABLE
  463. X
  464. XYou must specify one and only one variable to unset in your environment
  465. Xvariable settings.  Use printenv to print a list of all your environment
  466. Xvariables.
  467. X%%
  468. END_OF_FILE
  469. if test 16086 -ne `wc -c <'cmd_help'`; then
  470.     echo shar: \"'cmd_help'\" unpacked with wrong size!
  471. fi
  472. # end of 'cmd_help'
  473. fi
  474. if test -f 'fkeys.c' -a "${1}" != "-c" ; then 
  475.   echo shar: Will not clobber existing file \"'fkeys.c'\"
  476. else
  477. echo shar: Extracting \"'fkeys.c'\" \(13868 characters\)
  478. sed "s/^X//" >'fkeys.c' <<'END_OF_FILE'
  479. X/* @(#)fkeys.c        (c) copyright 10/18/86 (Dan Heller) */
  480. X
  481. X#include "mush.h"
  482. X#define draw(x1,y1,x2,y2,OP) pw_vector(msg_win, x1,y1,x2,y2,OP,1)
  483. X#define box(x1,y1,x2,y2,OP)  \
  484. X    draw(x1,y1, x1,y2,OP), draw(x1,y2, x2,y2,OP), \
  485. X        draw(x2,y2, x2,y1,OP), draw(x2,y1, x1,y1,OP)
  486. X
  487. Xstruct cmd fkey_cmds[] = {
  488. X    { "top", fkey_cmd }, { "close", fkey_cmd }, { "bottom", fkey_cmd },
  489. X    { "move", fkey_cmd }, { "stretch", fkey_cmd }, { "repaint", fkey_cmd },
  490. X    { "settings", fkey_settings }, { NULL, quit }
  491. X};
  492. X
  493. X#define L(n)        KEY_LEFTFIRST+(n)-1
  494. X#define R(n)        KEY_RIGHTFIRST+(n)-1
  495. X#define F(n)        KEY_TOPFIRST+(n)-1
  496. X#define BREAK_KEY    KEY_TOPLAST
  497. X
  498. Xchar *leftkey_default_settings[] = {
  499. X    "Left Function Key Settings",
  500. X    "Unused",        /* L1  */    "next",          /* L2  */
  501. X    "undelete",         /* L3  */    "delete",         /* L4  */
  502. X    "replyall",      /* L5  */    "replysender",       /* L6  */
  503. X    "mail",        /* L7  */    "Unset",        /* L8  */
  504. X    "lpr",          /* L9  */    "settings L",      /* L10 */
  505. X    0
  506. X};
  507. X
  508. Xchar *topkey_default_settings[] = {
  509. X    "Top Function Key Settings",
  510. X    "top",        /* T1  */     "close",            /* T2  */
  511. X    "move",        /* T3  */     "stretch",     /* T4  */
  512. X    "bottom",        /* T5  */     "repaint",       /* T6  */
  513. X    "Unset",        /* T7  */     "Unset",        /* T8  */
  514. X    "settings F",     /* T9  */
  515. X    0
  516. X};
  517. X
  518. Xchar *rightkey_default_settings[] = {
  519. X    "Right Function Key Settings",
  520. X    "Unset",        /* R1  */     "Unset",         /* R2  */
  521. X    "Unset",        /* R3  */     "Unset",         /* R4  */
  522. X    "Unset",        /* R5  */     "Unset",         /* R6  */
  523. X    "Unset",        /* R7  */     "Unset",         /* R8  */
  524. X    "Unset",        /* R9  */     "Unset",         /* R10 */
  525. X    "Unset",        /* R11 */     "Unset",         /* R12 */
  526. X    "Unset",        /* R13 */     "Unset",         /* R14 */
  527. X    "settings R",       /* R15 */
  528. X    0
  529. X};
  530. X
  531. X/*
  532. X * Execute commands defined by a function key.
  533. X * Left keys:
  534. X * L1 = (null)  can't be set
  535. X * L2 ... L10
  536. X * Top function keys
  537. X * F1 ... F9, BREAK/backspace (key not definable)
  538. X * Right function keys
  539. X * R1 ... R15
  540. X * Usually, the last Function key displays the others' settings.
  541. X */
  542. Xfkey(key)
  543. Xregister char *key;
  544. X{
  545. X    register char **argv, *p;
  546. X    char buf[256];
  547. X    int n;
  548. X
  549. X    /* user defined here...        ... default settings here */
  550. X    if (!strncmp((p = key_set_to(key)), "Un", 2)) {
  551. X    print("Funciton key: %s  %s", key, p);
  552. X    return 0;
  553. X    }
  554. X    /* make_command will screw up "p", so copy it first */
  555. X    (void) strcpy(buf, p);
  556. X    Debug("(%s) \"%s\": ", key, p), turnon(glob_flags, CONT_PRNT);
  557. X    if (argv = make_command(buf, TRPL_NULL, &n))
  558. X    (void) do_command(n, argv, msg_list);
  559. X    return -1;
  560. X}
  561. X
  562. Xfkey_settings(i, argv)
  563. Xregister char i;
  564. Xregister char **argv;
  565. X{
  566. X    register char key, *p, **fkey_str;
  567. X    char buf[256];
  568. X    char *help_args[17];
  569. X
  570. X    if (!*++argv) {
  571. X    print("Must specify one of L, F or R to identify a function key set");
  572. X    return -1;
  573. X    }
  574. X    key = **argv;
  575. X    switch(Upper(key)) {
  576. X    when 'L': fkey_str = leftkey_default_settings;
  577. X    when 'F': fkey_str = topkey_default_settings;
  578. X    when 'R': fkey_str = rightkey_default_settings;
  579. X    otherwise: print("Invalid key set: %c (choose L, F or R)", key);
  580. X           return -1;
  581. X    }
  582. X    help_args[0] = fkey_str[0];
  583. X    for (i = 1; fkey_str[i]; i++) {
  584. X    p = key_set_to(sprintf(buf, "%c%d", key, i));
  585. X    help_args[i] = savestr(sprintf(buf, "%c%-2.d       %s", key, i, p));
  586. X    }
  587. X    help_args[i] = 0;  /* null terminate list */
  588. X    (void) help(print_sw->ts_windowfd, help_args, NULL);
  589. X
  590. X    free_vec(help_args+1);
  591. X    return 0;
  592. X}
  593. X
  594. Xchar *
  595. Xkey_set_to(p)
  596. Xregister char *p;
  597. X{
  598. X    register char *p2, **fkey_str;
  599. X
  600. X    switch(*p) {
  601. X    when 'L': fkey_str = leftkey_default_settings;
  602. X    when 'F': fkey_str = topkey_default_settings;
  603. X    when 'R': fkey_str = rightkey_default_settings;
  604. X    }
  605. X    p2 = do_set(fkeys, p);
  606. X    return (p2)? p2: fkey_str[atoi(p+1)];
  607. X}
  608. X
  609. Xfkey_cmd(x, p)
  610. Xregister char **p;
  611. X{
  612. X    if (!strcmp(*p, "close"))
  613. X    toolquit(NO_ITEM, 0, NO_EVENT);
  614. X    else if (!strcmp(*p, "top"))
  615. X    wmgr_top(tool->tl_windowfd, rootfd);
  616. X    else if (!strcmp(*p, "move"))
  617. X    wmgr_move(tool->tl_windowfd, rootfd);
  618. X    else if (!strcmp(*p, "stretch"))
  619. X    wmgr_stretch(tool->tl_windowfd, rootfd);
  620. X    else if (!strcmp(*p, "bottom"))
  621. X    wmgr_bottom(tool->tl_windowfd, rootfd);
  622. X    else if (!strcmp(*p, "repaint"))
  623. X    wmgr_refreshwindow(tool->tl_windowfd, rootfd);
  624. X    return -1;
  625. X}
  626. X
  627. X/* execute a command given a function key, if the key is user defined,
  628. X * call fkey() at top of file. Parameter is the key number in "ascii"
  629. X */
  630. Xfunc_key(key)
  631. Xregister int key;
  632. X{
  633. X    register char *p;
  634. X    char buf[4];
  635. X    int nkey;
  636. X
  637. X    if (key >= KEY_LEFTFIRST && key <= KEY_LEFTLAST)
  638. X    buf[0] = 'L', nkey = key - KEY_LEFTFIRST;
  639. X    else if (key >= KEY_TOPFIRST && key <= KEY_TOPLAST)
  640. X    buf[0] = 'F', nkey = key - KEY_TOPFIRST;
  641. X    else if (key >= KEY_RIGHTFIRST && key <= KEY_RIGHTLAST)
  642. X    buf[0] = 'R', nkey = key - KEY_RIGHTFIRST;
  643. X    (void) sprintf(buf+1, "%d", nkey+1);
  644. X
  645. X    return fkey(buf);
  646. X}
  647. X
  648. Xvoid
  649. Xset_fkeys()
  650. X{
  651. X    ready(display_keys() + 10);
  652. X    print_valid_functions(txt.y+20);
  653. X    getting_opts = 2;
  654. X    win_setcursor(msg_sw->ts_windowfd, &checkmark);
  655. X}
  656. X
  657. Xchar *MSG = "Click the appropriate mouse button over a function key";
  658. Xready(Y)
  659. X{
  660. X    static int y;
  661. X    int x = (msg_rect.r_width - strlen(MSG)*l_width(LARGE))/2;
  662. X    if (Y)
  663. X    y = Y;
  664. X    Clrtoeol(msg_win, (txt.x = 0), (txt.y = y), LARGE);
  665. X    highlight(msg_win, x, y, LARGE, MSG);
  666. X}
  667. X
  668. X/* number of pixels in x and y directions describing the size of a graphical
  669. X * function key.  they represent the little keys and big keys respectively.
  670. X */
  671. X/* static struct pr_pos fkey_sizes[2] = { { 23, 23 }, { 50, 23 } }; */
  672. Xstatic struct pr_pos fkey_sizes[2] = { { 24, 23 }, { 52, 23 } };
  673. X
  674. X#define BORDER        4   /* border (distance) between keys */
  675. X#define KEYTOP        15  /* distance from top to start drawing */
  676. X#define LEFT_START    15  /* pixels from left to start drawing boxes */
  677. X#define TOP_START    (LEFT_START+2*fkey_sizes[0].x + fkey_sizes[1].x+BORDER)
  678. X#define RIGHT_START    (TOP_START + 5*(fkey_sizes[0].x+BORDER) + \
  679. X                     5*(fkey_sizes[1].x+BORDER))
  680. X
  681. X/*
  682. X * if !p, we're setting key at location x,y.
  683. X * else Set that key to this string (p).
  684. X */
  685. Xvoid
  686. Xset_key(p, x,y)
  687. Xregister char *p;
  688. Xregister int x,y;
  689. X{
  690. X    char     buf[256], **argv;
  691. X    static char *key;
  692. X    int     argc;
  693. X
  694. X    static int key_x, key_y;
  695. X    if (!p) {
  696. X    if (key = find_key(x,y)) {
  697. X        print("Type new setting for key: %s", key);
  698. X        (void) sprintf(buf, "Function key \"%s\": ", key);
  699. X        highlight(msg_win, 20, txt.y, LARGE, buf);
  700. X        txt.x = 20 + strlen(buf)*l_width(LARGE);
  701. X        Clrtoeol(msg_win, txt.x, txt.y, LARGE);
  702. X        pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], '_');
  703. X    } else
  704. X        ready(0);
  705. X    key_x = x, key_y = y;
  706. X    } else {
  707. X    int save_bang = ison(glob_flags, IGN_BANG);
  708. X    if (!*p)
  709. X        (void) sprintf(buf, "unfkey %s", key);
  710. X    else
  711. X        (void) sprintf(buf, "fkey %s \"%s\"", key, p);
  712. X    turnon(glob_flags, IGN_BANG);
  713. X    if (argv = make_command(buf, TRPL_NULL, &argc)) {
  714. X        (void) do_command(argc, argv, msg_list);
  715. X        print("Function key %s:  %s", key, key_set_to(key));
  716. X    }
  717. X    if (!save_bang)
  718. X        turnoff(glob_flags, IGN_BANG);
  719. X    ready(0);
  720. X    }
  721. X}
  722. X
  723. X/* passed the x and y coords of a mouse click, return the function key
  724. X * that exists in that position. NULL if no key there.  string will be
  725. X * something like "L6" or "F9" or "R12"
  726. X */
  727. Xchar *
  728. Xfind_key(x,y)
  729. Xint x, y;
  730. X{
  731. X    static char buf[6];
  732. X    int row, col;
  733. X    static int old_left, old_top, old_right, old_bot;
  734. X
  735. X    if (!(row = find_y(&y)))
  736. X    return NULL;
  737. X    if (x < LEFT_START || x > RIGHT_START + 3*(fkey_sizes[0].x+BORDER))
  738. X    return NULL;   /* out of range */
  739. X    if (x > LEFT_START && x < TOP_START-fkey_sizes[0].x - BORDER) {
  740. X    if ((col = (x > LEFT_START + fkey_sizes[0].x + BORDER)+1) == 1)
  741. X        x = LEFT_START+1;
  742. X    else x = LEFT_START + fkey_sizes[0].x + BORDER + 1;
  743. X    if (col == 1 && row == 1)
  744. X        return NULL;
  745. X    /* unhighlight the old function key image */
  746. X    if (old_left)
  747. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  748. X    old_left = x, old_top = y;
  749. X    old_right = x+fkey_sizes[(col != 1)].x-2, old_bot = y+fkey_sizes[0].y-2;
  750. X    /* highlight most recently selected function key image */
  751. X    box(x,y, old_right, old_bot, PIX_SRC);
  752. X
  753. X    return sprintf(buf, "L%d", col + 2*(row-1));
  754. X    }
  755. X    if (x > TOP_START && x < RIGHT_START - fkey_sizes[0].x - BORDER) {
  756. X    int which;
  757. X    if (row > 1)
  758. X        return NULL;
  759. X    which = (x - TOP_START) / (fkey_sizes[0].x + BORDER) + 1;
  760. X    if (which == 15)
  761. X        return NULL;   /* Can't set break key (backspace on a sun3) */
  762. X    if (which == 14)
  763. X        x = TOP_START + ((which = 9)-2) * (fkey_sizes[1].x+BORDER) -
  764. X            fkey_sizes[0].x - BORDER + 1;
  765. X    else if (which <= 2)
  766. X        x = TOP_START + (which-1) * (fkey_sizes[0].x+BORDER) + 1;
  767. X    else {
  768. X        which = (which+3)/2;
  769. X        x = TOP_START + (which-2) * (fkey_sizes[1].x+BORDER) + 1;
  770. X    }
  771. X
  772. X    /* unhighlight the old function key image */
  773. X    if (old_left)
  774. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  775. X    old_left = x, old_top = y;
  776. X    old_right = x+fkey_sizes[(which > 2 && which < 8)].x-2;
  777. X    old_bot = y+fkey_sizes[0].y-2;
  778. X    /* highlight most recently selected function key image */
  779. X    box(x,y, old_right, old_bot, PIX_SRC);
  780. X
  781. X    return sprintf(buf, "F%d", which);
  782. X    }
  783. X    if (x > RIGHT_START) {
  784. X    if (x < RIGHT_START + fkey_sizes[0].x)
  785. X        x = RIGHT_START+1, col = 1;
  786. X    else if (x < RIGHT_START + fkey_sizes[0].x + BORDER)
  787. X        return NULL;  /* cursor was clicked between keys */
  788. X    else if (x < RIGHT_START + 2*fkey_sizes[0].x + BORDER)
  789. X        x = RIGHT_START+fkey_sizes[0].x+BORDER+1, col = 2;
  790. X    else if (x < RIGHT_START + 2 * (fkey_sizes[0].x+BORDER))
  791. X        return NULL;  /* click between keys again */
  792. X    else x = RIGHT_START + 2*(fkey_sizes[0].x+BORDER)+1, col = 3;
  793. X
  794. X    /* unhighlight the old function key image */
  795. X    if (old_left)
  796. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  797. X    old_left = x, old_top = y;
  798. X    old_right = x+fkey_sizes[0].x-2, old_bot = y+fkey_sizes[0].y-2;
  799. X    /* highlight most recently selected function key image */
  800. X    box(x,y, old_right, old_bot, PIX_SRC);
  801. X
  802. X    return sprintf(buf, "R%d", col + 3*(row-1));
  803. X    }
  804. X    return NULL;
  805. X}
  806. X
  807. X/* find_y will find which row in a function key pad a y coordinate
  808. X * represents. return 1,2,3,4, or 5   0 if inbetween rows
  809. X */
  810. Xfind_y(y)
  811. Xregister int *y;
  812. X{
  813. X    int Y, y_incr = fkey_sizes[0].y, ret_value = 0;
  814. X    for (Y = KEYTOP; Y <= KEYTOP + 6*y_incr + 4 * BORDER; Y += y_incr + BORDER)
  815. X    if (*y < Y) {
  816. X        *y = (Y - y_incr - BORDER) + 1;
  817. X        return ret_value;
  818. X    } else ret_value++;
  819. X    return 0;
  820. X}
  821. X
  822. Xchar *l_msg = "Specifies which function key for setting value";
  823. Xchar *m_msg = "Display current value for function key";
  824. Xchar *r_msg = "Help setting and viewing function key values";
  825. X
  826. Xdisplay_keys()
  827. X{
  828. X    register int i, x,y;
  829. X    register char *p;
  830. X
  831. X    do_clear();
  832. X
  833. X    x = LEFT_START, y = KEYTOP;
  834. X    /* print left keys */
  835. X    for (i = 0; i < 10; i++) {
  836. X    box(x, y, x + fkey_sizes[i%2].x, y + fkey_sizes[i%2].y, PIX_SRC);
  837. X    box(x+2, y+2, x+fkey_sizes[i%2].x-2, y+fkey_sizes[i%2].y-2, PIX_SRC);
  838. X    if (i && (p = find_key(x+4,y+4)))
  839. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  840. X    else pw_replrop(msg_win, x+3, y+3, fkey_sizes[0].x-5, fkey_sizes[0].y-5,
  841. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  842. X    if (i % 2)
  843. X        y += fkey_sizes[0].y + BORDER, x = LEFT_START;
  844. X    else
  845. X        x += fkey_sizes[0].x + BORDER;
  846. X    }
  847. X
  848. X    x = TOP_START, y = KEYTOP;
  849. X    /* print top keys */
  850. X    for (i = 1; i <= 10; i++) {
  851. X    register int n = (i >= 3 && i <= 7);
  852. X    box(x, y, x + fkey_sizes[n].x, y + fkey_sizes[n].y, PIX_SRC);
  853. X    box(x+2, y+2, x + fkey_sizes[n].x-2, y + fkey_sizes[n].y-2, PIX_SRC);
  854. X    if (i != 10 && (p = find_key(x+4,y+4)))
  855. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  856. X    /* shade the break key (backspace on sun3's) -- can't set */
  857. X    else if (i == 10)
  858. X        pw_replrop(msg_win, x+3, y+3, fkey_sizes[n].x-5, fkey_sizes[n].y-5,
  859. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  860. X    x += fkey_sizes[n].x + BORDER;
  861. X    }
  862. X
  863. X    x = RIGHT_START;
  864. X    /* print right keys */
  865. X    for (i = 0; i < 15; i++) {
  866. X    box(x, y, x + fkey_sizes[0].x, y + fkey_sizes[0].y, PIX_SRC);
  867. X    box(x+2, y+2, x + fkey_sizes[0].x-2, y + fkey_sizes[0].y-2, PIX_SRC);
  868. X    if (p = find_key(x+4,y+4))
  869. X        pw_text(msg_win, x+3, y+3+l_height(SMALL),PIX_SRC, fonts[SMALL], p);
  870. X    if (!((i+1) % 3))
  871. X        y += fkey_sizes[0].y + BORDER, x -= 2*(fkey_sizes[0].x + BORDER);
  872. X    else
  873. X        x += fkey_sizes[0].x + BORDER;
  874. X    }
  875. X    x = TOP_START;
  876. X    y = KEYTOP + BORDER + fkey_sizes[0].y + l_height(DEFAULT);
  877. X    pw_rop(msg_win, x, y-11, 16,16, PIX_SRC, &mouse_left, 0,0);
  878. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], l_msg);
  879. X
  880. X    y += BORDER + fkey_sizes[0].y;
  881. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_middle, 0,0);
  882. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], m_msg);
  883. X
  884. X    y += BORDER + fkey_sizes[0].y;
  885. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_right, 0,0);
  886. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], r_msg);
  887. X
  888. X    x = (msg_rect.r_width - 26*l_width(DEFAULT))/2;
  889. X    y += BORDER + fkey_sizes[0].y;
  890. X    highlight(msg_win, x, y, DEFAULT, "You may not set shaded keys");
  891. X
  892. X    y += BORDER + fkey_sizes[0].y + 15;
  893. X    for (i = 0; i < BORDER; i++)
  894. X    draw(0, y+i, msg_rect.r_width, y+i, PIX_SRC);
  895. X    y += 10;
  896. X    for (i = 0; i < BORDER; i++)
  897. X    draw(0, y+l_height(LARGE)+i, msg_rect.r_width, y+l_height(LARGE)+i,
  898. X         PIX_SRC);
  899. X    return y;
  900. X}
  901. X
  902. Xprint_valid_functions(y)
  903. Xregister int y;
  904. X{
  905. X    register int x, n, cmd_len = 12 * l_width(DEFAULT);
  906. X    register char *p;
  907. X
  908. X    y += 20, x = (msg_rect.r_width - 25*l_width(LARGE))/2;
  909. X    highlight (msg_win, x, y, LARGE, "Available Command Names");
  910. X    y += 20, x = 30;
  911. X    for (n = 0; p = cmds[n].command; n++) {
  912. X    if (x + cmd_len > msg_rect.r_width - 5)
  913. X        y += l_height(DEFAULT), x = 30;
  914. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  915. X    x += cmd_len;
  916. X    }
  917. X    for (n = 0; p = fkey_cmds[n].command; n++) {
  918. X    if (x + cmd_len > msg_rect.r_width - 5)
  919. X        y += l_height(DEFAULT), x = 30;
  920. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  921. X    x += cmd_len;
  922. X    }
  923. X}
  924. END_OF_FILE
  925. if test 13868 -ne `wc -c <'fkeys.c'`; then
  926.     echo shar: \"'fkeys.c'\" unpacked with wrong size!
  927. fi
  928. # end of 'fkeys.c'
  929. fi
  930. if test -f 'select.c' -a "${1}" != "-c" ; then 
  931.   echo shar: Will not clobber existing file \"'select.c'\"
  932. else
  933. echo shar: Extracting \"'select.c'\" \(13090 characters\)
  934. sed "s/^X//" >'select.c' <<'END_OF_FILE'
  935. X/* select.c    (c) copyright 1986 (Dan Heller) */
  936. X
  937. X/* 
  938. X * Routine which handle io (selection on file descriptors) between user and
  939. X * the various windows.
  940. X *
  941. X * In toolmode, the user types characters and each character is interpreted
  942. X * here and, if applicable, is sent to rite.c where it is appended to a 
  943. X * string similar to a tty driver and fgets. When the user types a '\n' the
  944. X * rite() routine returns the string and we call add_to_letter to append the
  945. X * string to the letter.  Signals are caught here as well.  that is the signal
  946. X * characters setup by the user are checked and if one matches, call the signal
  947. X * handling routine as if there were a real signal.
  948. X *
  949. X * Mouse handling is done here. See code for more detail.
  950. X */
  951. X#include "mush.h"
  952. X#define swap(a,b)         (a ^= b ^= a)   /* swap values of a pair of ints */
  953. X
  954. X#define READ_MSG    (char *)'r'
  955. X#define DEL_MSG        (char *)'d'
  956. X#define UNDEL_MSG    (char *)'u'
  957. X#define REPL_MSG    (char *)'R'
  958. X#define SAVE_MSG    (char *)'s'
  959. X#define PRNT_MSG    (char *)'p'
  960. X#define PRE_MSG        (char *)'P'
  961. X#define E_EDIT         (char *)'e'
  962. X#define E_VIEW         (char *)'v'
  963. X#define E_INCLUDE      (char *)'i'
  964. X#define E_SEND        (char *)'S'
  965. X#define E_ABORT       (char *)'a'
  966. X#define MENU_HELP    (char *)'h'
  967. X#define O_SAVE        (char *)'s'
  968. X#define O_QUIT        (char *)'q'
  969. X#define O_RSTR        (char *)'r'
  970. X
  971. X#define N_MENU_ITEMS    8
  972. X#define E_MENU_ITEMS    6
  973. X
  974. Xmsg_io(gfxsw, ibits, obits, ebits, timer)
  975. Xregister struct gfxsubwindow *gfxsw;
  976. Xregister int *ibits,*obits,*ebits;
  977. Xstruct timeval **timer;
  978. X{
  979. X    register char    *p;
  980. X    struct inputevent     event;
  981. X    static char     lastchar;
  982. X    static int         line, count;
  983. X
  984. X    if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  985. X    *ibits = *obits = *ebits = 0;
  986. X    return;
  987. X    }
  988. X    if (input_readevent(msg_sw->ts_windowfd, &event) == -1) {
  989. X    error("input event");
  990. X    return;
  991. X    }
  992. X    /*
  993. X    if (ID == LOC_WINENTER) {
  994. X    int x;
  995. X    struct inputmask im;
  996. X    win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  997. X    win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  998. X    }
  999. X    */
  1000. X    if (ID >= KEY_LEFTFIRST)
  1001. X    if (ison(glob_flags, IS_GETTING))
  1002. X        print("Finish editing letter first");
  1003. X    else
  1004. X        (void) func_key(ID);
  1005. X    else if (isascii(ID) && (msg_pix || ison(glob_flags, IS_GETTING) ||
  1006. X    getting_opts)) {
  1007. X    if (getting_opts) {
  1008. X        /*
  1009. X         * txt.x <= 5 indicates not to accept typed input for options
  1010. X         * and function key setting.
  1011. X         */
  1012. X        if (txt.x > 5) {
  1013. X        /* ^C, ^\ or ^U kills line */
  1014. X        pw_char(msg_win, txt.x,txt.y, PIX_OR, fonts[curfont], '_');
  1015. X        if (ID == tchars.t_intrc || ID == tchars.t_quitc ||
  1016. X                        ID == _tty.sg_kill) {
  1017. X            rite(_tty.sg_kill), txt.x = 5;
  1018. X            if (getting_opts == 1)
  1019. X            option_line(line), display_opts(0);
  1020. X            else
  1021. X            set_key(0, 0, 0);
  1022. X        } else if (p = rite((char)ID)) {
  1023. X            /* if no string entered, preserve old value */
  1024. X            if (*p && getting_opts == 1)
  1025. X            add_opt(p, line);
  1026. X            if (getting_opts == 2)
  1027. X            set_key(p, 0,0);
  1028. X        } else
  1029. X            pw_char(msg_win, txt.x, txt.y, PIX_OR, fonts[curfont], '_');
  1030. X        }
  1031. X    }
  1032. X    /*
  1033. X     * This section MUST BE BEFORE the following "is_getting" section.
  1034. X     * If user displays a message while editing a letter, he must hit 'q'
  1035. X     * to return to edit mode.  He may not edit a new letter while one is
  1036. X     * already being edited.
  1037. X     */
  1038. X    else if (msg_pix)
  1039. X        if (isdigit(ID)) {
  1040. X        if (!isdigit(lastchar))
  1041. X            count = 0;
  1042. X        count = count * 10 + ID - '0';
  1043. X        } else {
  1044. X        /* scroll <count> lines */
  1045. X        if (!count || count > msg_pix->pr_size.y / l_height(curfont))
  1046. X            count = 1;
  1047. X        if (ID == 'k' || ID == 'K' || ID == '-')
  1048. X            scroll_win(-count);
  1049. X        else if (ID == '\n' || ID == '\r' || ID == 'j')
  1050. X            scroll_win(count);
  1051. X        else if (ID == ' ')
  1052. X            scroll_win(crt);
  1053. X        else if ((ID == 'q' || ID == 'Q') &&
  1054. X            ison(glob_flags, IS_GETTING)) {
  1055. X            pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
  1056. X            win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  1057. X            txt.x = 5, txt.y = msg_rect.r_height - l_height(curfont);
  1058. X            wprint("\n(continue editing letter)\n");
  1059. X            clr_bot_line();
  1060. X            pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_');
  1061. X        }
  1062. X        }
  1063. X    /*
  1064. X     * If msg_pix is NULL, then we are not reading a message. If we are
  1065. X     * editing a letter, then enter the keys typed.  If we are doing
  1066. X     * nothing, ignore this input.
  1067. X     */
  1068. X    else if (ison(glob_flags, IS_GETTING)) {
  1069. X        pw_char(msg_win, txt.x,txt.y, PIX_SRC^PIX_DST, fonts[curfont],'_');
  1070. X        if (lastchar != ltchars.t_lnextc &&
  1071. X        (ID == tchars.t_intrc || ID == tchars.t_quitc)) {
  1072. X            (void) rite(_tty.sg_kill);
  1073. X            (void) rm_edfile(SIGINT);
  1074. X        } else {
  1075. X        register int n = 1;
  1076. X        if (ID == tchars.t_eofc && txt.x == 5
  1077. X            || (p = rite((char)ID)) && !(n = add_to_letter(p)))
  1078. X            finish_up_letter();
  1079. X        else if (n > 0)
  1080. X            pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_');
  1081. X        }
  1082. X    }
  1083. X    lastchar = ID;
  1084. X    } else switch(ID) {
  1085. X    when MS_LEFT : case MS_MIDDLE:
  1086. X        if (getting_opts == 2)
  1087. X        if (ID == MS_LEFT)
  1088. X            set_key(NULL, event.ie_locx, event.ie_locy);
  1089. X        else {
  1090. X            register char *p = find_key(event.ie_locx, event.ie_locy);
  1091. X            if (p)
  1092. X            print("Function key %s:  %s", p, key_set_to(p));
  1093. X        }
  1094. X        else if (getting_opts) {
  1095. X        int y = event.ie_locy - 50;
  1096. X        if (y < -24)
  1097. X            break;
  1098. X        if (y < 0) {
  1099. X            register int x = event.ie_locx;
  1100. X            register int X = 60*l_width(LARGE);
  1101. X            if (x >= X && x <= X+16)
  1102. X            display_opts(-1); /* scroll options back one value */
  1103. X            else if (x >= X+20 && x <= X+36)
  1104. X            display_opts(1); /* scroll options forward one value */
  1105. X            break;
  1106. X        }
  1107. X        /* the user was typing something -- stopped by using mouse */
  1108. X        if (txt.x > 5) {
  1109. X            pw_char(msg_win, txt.x,txt.y, PIX_CLR, fonts[curfont], '_');
  1110. X            (void) rite(_tty.sg_kill), txt.x = 5;
  1111. X            option_line(line), display_opts(0);
  1112. X        }
  1113. X            line = y/20;
  1114. X        if (ID == MS_LEFT)
  1115. X            toggle_opt(line);
  1116. X        help_opt(line);   /* display help (short info) in both cases */
  1117. X        } else if (msg_pix)
  1118. X        if (ID == MS_LEFT)
  1119. X            scroll_win(crt-3);
  1120. X        else
  1121. X            scroll_win(-(crt-3));
  1122. X    when MS_RIGHT:
  1123. X        if (getting_opts)
  1124. X        (void) view_opts_menu(&event, gfxsw->gfx_windowfd);
  1125. X        else if (isoff(glob_flags, IS_GETTING))
  1126. X        (void) do_menu(&event, gfxsw->gfx_windowfd, current_msg);
  1127. X        else
  1128. X        (void) edit_menu(&event, gfxsw->gfx_windowfd);
  1129. X    otherwise: ;
  1130. X    }
  1131. X    *ibits = *obits = *ebits = 0;
  1132. X}
  1133. X
  1134. Xstruct cursor *mice[3] = { &l_cursor, &m_cursor, &r_cursor };
  1135. X
  1136. Xhdr_io(gfxsw, ibits, obits, ebits, sw_timer)
  1137. Xregister struct gfxsubwindow *gfxsw;
  1138. Xint *ibits,*obits,*ebits;
  1139. Xstruct timeval **sw_timer;
  1140. X{
  1141. X    static int         which_cursor;
  1142. X    struct inputmask     im;
  1143. X    struct inputevent     event;
  1144. X    int         line;
  1145. X
  1146. X    if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  1147. X    *ibits = *obits = *ebits = 0;
  1148. X    return;
  1149. X    }
  1150. X    /* make curosr change which button is lit */
  1151. X    win_setcursor(gfxsw->gfx_windowfd, mice[which_cursor]);
  1152. X
  1153. X    which_cursor = (which_cursor+1) % 3;
  1154. X    if (input_readevent(hdr_sw->ts_windowfd, &event) == -1) {
  1155. X    error("input event");
  1156. X    return;
  1157. X    }
  1158. X    /* I'm not sure why I have to do this.
  1159. X     * I'm doing it because sometimes the IO hangs completely and no input
  1160. X     * is accepted. What I do here is get the current mask, save it, then
  1161. X     * reset it. This action seems to flush the IO queue, and I don't have hung
  1162. X     * IO anymore.  This shouldn't be necessary, but it appears to work.
  1163. X     * (occurances have droped about 90%)
  1164. X     */
  1165. X    if (ID == LOC_WINENTER) {
  1166. X    int x;
  1167. X    win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  1168. X    win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  1169. X    }
  1170. X    /* just return -- we just wanted to make the cursor flicker */
  1171. X    if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER) {
  1172. X    *ibits = *obits = *ebits = 0;
  1173. X    return;
  1174. X    }
  1175. X    line = event.ie_locy / l_height(DEFAULT);
  1176. X    if (ID >= KEY_LEFTFIRST)
  1177. X    (void) func_key(ID);
  1178. X    else if (n_array[line] > msg_cnt)
  1179. X    if (!msg_cnt)
  1180. X        print("You have no messages -- this function is useless now.");
  1181. X    else
  1182. X        print("Message out of range.  Place mouse over a legal message.");
  1183. X    else switch(ID) {
  1184. X    when MS_LEFT: case MS_MIDDLE:
  1185. X        (void) do_menu((ID == MS_LEFT)? READ_MSG: DEL_MSG, 0,n_array[line]);
  1186. X    when MS_RIGHT:
  1187. X        (void) do_menu(&event, gfxsw->gfx_windowfd, n_array[line]);
  1188. X    otherwise : print("Unkown ID = %d", ID);
  1189. X    }
  1190. X    *ibits = *obits = *ebits = 0;
  1191. X}
  1192. X
  1193. X/* if "fd" is 0, then event points to the action to be taken.
  1194. X * otherwise, determine action to be taken by displaying a menu.
  1195. X * message is the number current_msg should be changed to (may be the same).
  1196. X */
  1197. Xdo_menu(event, fd, message)
  1198. Xcaddr_t event;
  1199. X{
  1200. X    static char buf[20];
  1201. X    struct menuitem *m_item;
  1202. X    char *action;
  1203. X    static struct menuitem msg_menu_items[] = {
  1204. X    { MENU_IMAGESTRING,  "Read",     READ_MSG   },
  1205. X    { MENU_IMAGESTRING,  "Delete",   DEL_MSG    },
  1206. X    { MENU_IMAGESTRING,  "Undelete", UNDEL_MSG  },
  1207. X    { MENU_IMAGESTRING,  "Reply",    REPL_MSG   },
  1208. X    { MENU_IMAGESTRING,  "Save",     SAVE_MSG   },
  1209. X    { MENU_IMAGESTRING,  "Preserve", PRE_MSG    },
  1210. X    { MENU_IMAGESTRING,  "Print",    PRNT_MSG   },
  1211. X    { MENU_IMAGESTRING,  "Help",     MENU_HELP  }
  1212. X    };
  1213. X    static struct menu help_menu = {
  1214. X        MENU_IMAGESTRING, "Item Help",
  1215. X    N_MENU_ITEMS, msg_menu_items,
  1216. X    (struct menu *)NULL, NULL
  1217. X    };
  1218. X    static struct menu msgs_menu = {
  1219. X        MENU_IMAGESTRING, buf, N_MENU_ITEMS,
  1220. X    msg_menu_items, &help_menu, NULL
  1221. X    };
  1222. X    /* to have the menu stack maintain order of menus upon each invokation,
  1223. X     * declare menu_ptr to be static and remove the following two lines
  1224. X     * after the declaration.
  1225. X     */
  1226. X    struct menu *menu_ptr = &msgs_menu;
  1227. X    msgs_menu.m_next = &help_menu;
  1228. X    help_menu.m_next = (struct menu *)NULL;
  1229. X
  1230. X    if (!msg_cnt) {
  1231. X    print("No Messages.");
  1232. X    return;
  1233. X    }
  1234. X    if (fd) {
  1235. X    (void) sprintf(buf, "Message #%d", message+1);
  1236. X    if (m_item = menu_display(&menu_ptr, (struct inputevent *)event, fd))
  1237. X        action = m_item->mi_data;
  1238. X    else
  1239. X        return;
  1240. X    } else
  1241. X    action = event;
  1242. X
  1243. X    if (menu_ptr == &help_menu || action == MENU_HELP) {
  1244. X    switch(action) {
  1245. X        when DEL_MSG: case UNDEL_MSG:
  1246. X        (void) help(fd, "menu_delete", tool_help);
  1247. X        when READ_MSG: (void) help(fd, "next", tool_help);
  1248. X        when REPL_MSG: (void) help(fd, "menu_respond", tool_help);
  1249. X        when SAVE_MSG: (void) help(fd, "save", tool_help);
  1250. X        when PRE_MSG: (void)  help(fd, "preserve", tool_help);
  1251. X        when PRNT_MSG: (void) help(fd, "printer", tool_help);
  1252. X        when MENU_HELP:
  1253. X        if (menu_ptr == &help_menu)
  1254. X            (void) help(fd, "help_menu_help_msg", tool_help);
  1255. X        else
  1256. X            (void) help(fd, "msg_menu", tool_help);
  1257. X    }
  1258. X    return;
  1259. X    }
  1260. X    set_isread(message);
  1261. X    if (action == SAVE_MSG) {
  1262. X    swap(current_msg, message);
  1263. X    ((struct inputevent *)event)->ie_code = MS_LEFT;
  1264. X    do_file_dir(save_item, 0, event);
  1265. X    swap(current_msg, message);
  1266. X    return;
  1267. X    } else if (action == PRNT_MSG  || action == PRE_MSG ||
  1268. X           action == UNDEL_MSG || action == DEL_MSG) {
  1269. X    fkey_misc(action, message);
  1270. X    return;
  1271. X    }
  1272. X    if (isoff(glob_flags, IS_GETTING)) {
  1273. X    current_msg = message;
  1274. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  1275. X    }
  1276. X    if (action == REPL_MSG) {
  1277. X    respond_mail(respond_item, 0, event);
  1278. X    return;
  1279. X    } else if (ison(glob_flags, IS_GETTING)) {
  1280. X    print("Finish editing message first");
  1281. X    return;
  1282. X    }
  1283. X    display_msg(current_msg, (long)0);
  1284. X}
  1285. X
  1286. X/* miscellaneous function key actions there are here because the defines
  1287. X * for DEL_MSG, etc are here in this file and the function is called from
  1288. X * here more often.
  1289. X */
  1290. Xfkey_misc(action, message)
  1291. Xchar *action;
  1292. X{
  1293. X    int argc;
  1294. X    register char **argv;
  1295. X    char buf[30];
  1296. X
  1297. X    print("Message #%d ", message+1);
  1298. X    if (action == UNDEL_MSG || action == DEL_MSG)
  1299. X    print_more("%sd. ", sprintf(buf, "%selete",
  1300. X                (action == DEL_MSG)? "d": "und"));
  1301. X    else if (action == PRNT_MSG) {
  1302. X    print_more("sent to printer");
  1303. X    (void) strcpy(buf, "lpr");
  1304. X    } else if (action == PRE_MSG)
  1305. X    print_more("%sd", strcpy(buf, "preseve"));
  1306. X    (void) sprintf(&buf[strlen(buf)], " %d", message+1);
  1307. X
  1308. X    if (argv = make_command(buf, DUBL_NULL, &argc))
  1309. X    (void) do_command(argc, argv, msg_list);
  1310. X    return;
  1311. X}
  1312. X
  1313. Xview_opts_menu(event, fd)
  1314. Xstruct inputevent *event;
  1315. X{
  1316. X    static char buf[5];
  1317. X    struct menuitem *m_item;
  1318. X    char *action;
  1319. X    static struct menuitem opts_items[] = {
  1320. X    { MENU_IMAGESTRING,  "Save Options",    O_SAVE  },
  1321. X    { MENU_IMAGESTRING,  "Restore Options",    O_RSTR  },
  1322. X    { MENU_IMAGESTRING,  "Quit Options",    O_QUIT  },
  1323. X    { MENU_IMAGESTRING,  "Help",        MENU_HELP  }
  1324. X    };
  1325. X    static struct menu msgs_menu = {
  1326. X        MENU_IMAGESTRING, "Options", 4, opts_items, (struct menu *)NULL, NULL
  1327. X    };
  1328. X    struct menu *menu_ptr = &msgs_menu;
  1329. X
  1330. X    if (m_item = menu_display(&menu_ptr, event, fd))
  1331. X    action = m_item->mi_data;
  1332. X    else
  1333. X    return;
  1334. X    switch(action) {
  1335. X    case O_SAVE:
  1336. X        save_opts(0, DUBL_NULL);
  1337. X    when O_RSTR:
  1338. X        init();
  1339. X        if (getting_opts == 1)
  1340. X        view_options();
  1341. X        else
  1342. X        set_fkeys();
  1343. X    when O_QUIT:
  1344. X        do_clear();
  1345. X        unlock_cursors(); /* actually resets msg_win's cursor */
  1346. X        if (isoff(glob_flags, IS_GETTING) && msg_cnt)
  1347. X        if (isoff(msg[current_msg].m_flags, DELETE))
  1348. X            display_msg(current_msg, (long)0);
  1349. X        else
  1350. X            (void) read_mail(NO_ITEM, 0, NO_EVENT);
  1351. X    when MENU_HELP:
  1352. X        (void) help(fd, (getting_opts == 1)? "options": "fkeys", tool_help);
  1353. X    }
  1354. X}
  1355. END_OF_FILE
  1356. if test 13090 -ne `wc -c <'select.c'`; then
  1357.     echo shar: \"'select.c'\" unpacked with wrong size!
  1358. fi
  1359. # end of 'select.c'
  1360. fi
  1361. echo shar: End of archive 5 \(of 12\).
  1362. cp /dev/null ark5isdone
  1363. MISSING=""
  1364. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1365.     if test ! -f ark${I}isdone ; then
  1366.     MISSING="${MISSING} ${I}"
  1367.     fi
  1368. done
  1369. if test "${MISSING}" = "" ; then
  1370.     echo You have unpacked all 12 archives.
  1371.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1372. else
  1373.     echo You still need to unpack the following archives:
  1374.     echo "        " ${MISSING}
  1375. fi
  1376. ##  End of shell archive.
  1377. exit 0
  1378.